package net.airtheva.uniqueTask4.fragment;

import java.io.File;

import net.airtheva.uniqueTask4.LyricParser;
import net.airtheva.uniqueTask4.PlayerService;
import net.airtheva.uniqueTask4.Playitem;
import net.airtheva.uniqueTask4.R;
import net.airtheva.uniqueTask4.Utils;
import net.airtheva.uniqueTask4.lyricLoader.GecimeLyricLoader;
import net.airtheva.uniqueTask4.view.FloatLyricView;
import net.airtheva.uniqueTask4.view.LyricScrollView;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.PixelFormat;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.GestureDetector;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

public class PlayingFragment extends Fragment {

	public static final String TAG = "PlayingFragment";
	
	public static final int INTERVAL = 500;
	
	class _BroadcastReceiver extends BroadcastReceiver {

		@Override
		public void onReceive(Context context, Intent intent) {
			// TODO Auto-generated method stub
			
			Update();
			
		}
		
	}
	
	class LoadLyricAsyncTask extends AsyncTask<String, Void, String> {

		@Override
		protected String doInBackground(String... params) {
			// TODO Auto-generated method stub
			
			Log.d(TAG, "LoadAsyncTask started.");
			GecimeLyricLoader gll = new GecimeLyricLoader(params[0], params[1]);
			String lyric = gll.GetLyric();
			Log.d(TAG, "LoadAsyncTask ended.");
			
			return lyric;
		}

		@Override
		protected void onPostExecute(String result) {
			// TODO Auto-generated method stub
			//super.onPostExecute(result);
			
			if(result == null) {
				
				// FIXME: Debugging.
				String lyric = Utils.ReadFile(new File("/sdcard/x.lrc"));
				LyricParser lp = new LyricParser(lyric);
				mLyricScrollView.SetLyricParser(lp);
				
				Toast.makeText(getActivity(), "NO_LYRIC_FOUND", Toast.LENGTH_SHORT).show();
				
			}
			else {
				
				LyricParser lp = new LyricParser(result);
				
				mLyricScrollView.SetLyricParser(lp);
				Utils.GetPlayerService(PlayingFragment.this).SetLyricParser(lp);
				
				//Log.d(TAG, Utils.Join(lp.GetTimes(), ", "));
				//Log.d(TAG, Utils.Join(lp.GetLines(), ", "));
				
				mIsLyricLoaded = true;
				
			}
			
		}
		
	}
	
	class Updater implements Runnable {

		@Override
		public void run() {
			// TODO Auto-generated method stub
			
			if(!Update()) {
				mHandler.postDelayed(this, INTERVAL);
			}
			
		}
		
	}
	
	class Walker implements Runnable {

		@Override
		public void run() {
			// TODO Auto-generated method stub
			
			if(mCurrentTime < mTotalTime) { // Walk.
				
				mCurrentTime = mCurrentTime + INTERVAL;
				
				mLyricScrollView.SetTime(mCurrentTime);
				mTime.setText(mCurrentTime + "");
				mSeekBar.setProgress(mCurrentTime);
				
				mHandler.postDelayed(this, INTERVAL);
				
			}
			else { // Finish.
				
				mHandler.removeCallbacks(this);
				
				mHandler.post(mUpdater);
				
			}
			
		}
		
	}
	
	Handler mHandler;
	Updater mUpdater;
	Walker mWalker;
	
	_BroadcastReceiver mBroadcastReceiver;
	
	TextView mInformation;
	
	ImageView mIcon;
	LyricScrollView mLyricScrollView;
	
	ImageView mMode;
	
	TextView mTime;
	SeekBar mSeekBar;
	
	ImageButton mPrevious;
	ImageButton mToggle;
	ImageButton mNext;
	
	LyricSearchDialog mLyricSearchDialog;
	
	Playitem mCurrentPlayitem;
	int mTotalTime;
	int mCurrentTime;
	int mCurrentMode;
	
	boolean mIsLyricLoaded = false;
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		
		mHandler = new Handler();
		mUpdater = new Updater();
		
		mWalker = new Walker();
		
		mBroadcastReceiver = new _BroadcastReceiver();
		
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		View view = inflater.inflate(R.layout.fragment_playing, null);
		
		mInformation = (TextView) view.findViewById(R.id.fragment_playing_information);
		
		mIcon = (ImageView) view.findViewById(R.id.fragment_playing_icon);
		
		mLyricScrollView = (LyricScrollView) view.findViewById(R.id.fragment_playing_lyricScrollView);
		mLyricScrollView.setOnTouchListener(new View.OnTouchListener() {
			
			GestureDetector mGestureDetector = new GestureDetector(getActivity(), new GestureDetector.OnGestureListener() {
				
				@Override
				public boolean onSingleTapUp(MotionEvent e) {
					// TODO Auto-generated method stub
					
					ShowLyricSearchDialog();
					
					return false;
				}
				
				@Override
				public void onShowPress(MotionEvent e) {
					// TODO Auto-generated method stub
					
				}
				
				@Override
				public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
						float distanceY) {
					// TODO Auto-generated method stub
					return false;
				}
				
				@Override
				public void onLongPress(MotionEvent e) {
					// TODO Auto-generated method stub
					
				}
				
				@Override
				public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
						float velocityY) {
					// TODO Auto-generated method stub
					return false;
				}
				
				@Override
				public boolean onDown(MotionEvent e) {
					// TODO Auto-generated method stub
					return false;
				}
				
			});
			
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				// TODO Auto-generated method stub
				
				if(!mGestureDetector.onTouchEvent(event)) {
					
					switch(event.getAction()) {
					case MotionEvent.ACTION_DOWN:
						mLyricScrollView.StartSeeking();
						break;
					case MotionEvent.ACTION_MOVE:
						mLyricScrollView.UpdateSeeking();
						break;
					case MotionEvent.ACTION_UP:
						mLyricScrollView.EndSeeking();
						break;
					}
					
					return false;
					
				}
				else {
					return true;
				}
				
			}
		});
		mLyricScrollView.SetOnTimeChangedListener(new LyricScrollView.OnTimeChangedListener() {
			
			@Override
			public void OnTimeChanged(int newTime) {
				// TODO Auto-generated method stub
				
				Seek(newTime);
				Update();
				
			}
			
		});
		
		mMode = (ImageView) view.findViewById(R.id.fragment_playing_mode);
		mMode.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				SwitchMode();
				Update();
			}
		});
		
		mTime = (TextView) view.findViewById(R.id.fragment_playing_time);
		
		mSeekBar = (SeekBar) view.findViewById(R.id.fragment_playing_seekBar);
		mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
			
			@Override
			public void onStopTrackingTouch(SeekBar seekBar) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void onStartTrackingTouch(SeekBar seekBar) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void onProgressChanged(SeekBar seekBar, int progress,
					boolean fromUser) {
				// TODO Auto-generated method stub
				
				if(fromUser) {
					Seek(progress);
					Update();
				}
				
			}
		});
		
		mPrevious = (ImageButton) view.findViewById(R.id.fragment_playing_previous);
		mPrevious.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				
				PlayerService playerService = Utils.GetPlayerService(PlayingFragment.this);
				playerService.Previous();
				
				mHandler.post(mUpdater);
				
			}
			
		});
		
		mToggle = (ImageButton) view.findViewById(R.id.fragment_playing_toggle);
		mToggle.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				
				PlayerService playerService = Utils.GetPlayerService(PlayingFragment.this);
				playerService.Toggle();
				
				mHandler.post(mUpdater);
				
			}
			
		});
		
		mNext = (ImageButton) view.findViewById(R.id.fragment_playing_next);
		mNext.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				
				PlayerService playerService = Utils.GetPlayerService(PlayingFragment.this);
				playerService.Next();
				
				mHandler.post(mUpdater);
				
			}
			
		});
		
		return view;
	}

	@Override
	public void setUserVisibleHint(boolean isVisibleToUser) {
		// TODO Auto-generated method stub
		super.setUserVisibleHint(isVisibleToUser);
		
		// Force to update when user sees this fragment.
		if(isVisibleToUser) {
			mHandler.post(mUpdater);
		}
		
	}
	
	@Override
	public void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		
		Utils.GetPlayerService(this).HideFloatLyricView();
		
		getActivity().registerReceiver(mBroadcastReceiver, new IntentFilter(PlayerService.BROADCAST_PREVIOUS));
		getActivity().registerReceiver(mBroadcastReceiver, new IntentFilter(PlayerService.BROADCAST_TOGGLE));
		getActivity().registerReceiver(mBroadcastReceiver, new IntentFilter(PlayerService.BROADCAST_NEXT));

		// When resumed, update.
		mHandler.post(mUpdater);
		
	}

	@Override
	public void onPause() {
		// TODO Auto-generated method stub
		
		mHandler.removeCallbacks(mWalker);
		mHandler.removeCallbacks(mUpdater);
		
		getActivity().unregisterReceiver(mBroadcastReceiver);

		Utils.GetPlayerService(this).ShowFloatLyricView();
		
		super.onPause();
	}

	public void ShowLyricSearchDialog() {
		
		if(mCurrentPlayitem != null) {
			
			mLyricSearchDialog = new LyricSearchDialog();
			Bundle args = new Bundle();
			args.putString("artist", mCurrentPlayitem.Artist);
			args.putString("title", mCurrentPlayitem.Title);
			mLyricSearchDialog.setArguments(args);
			
			mLyricSearchDialog.SetPositiveClick(new DialogInterface.OnClickListener() {
				
				@Override
				public void onClick(DialogInterface dialog, int which) {
					// TODO Auto-generated method stub
					LoadLyric(mLyricSearchDialog.GetArtist(), mLyricSearchDialog.GetTitle());
					mLyricSearchDialog.dismiss();
				}
				
			});
			
			mLyricSearchDialog.SetNegativeClick(new DialogInterface.OnClickListener() {
				
				@Override
				public void onClick(DialogInterface dialog, int which) {
					// TODO Auto-generated method stub
					mLyricSearchDialog.dismiss();
				}
				
			});
			
			mLyricSearchDialog.show(getChildFragmentManager(), LyricSearchDialog.TAG);
			
		}
		
	}
	
	public void LoadLyric(String artist, String title) {
		
		(new LoadLyricAsyncTask()).execute(new String[] { artist, title });
		
	}
	
	public void Seek(int time) {
		
		Utils.GetPlayerService(this).Seek(time);
		
	}
	
	public void SwitchMode() {
		
		PlayerService playerService = Utils.GetPlayerService(this);
		if(mCurrentMode >= PlayerService.MODE_RANDOM) {
			playerService.SetMode(0);
		}
		else {
			playerService.SetMode(mCurrentMode + 1);
		}
		
	}
	
	public void SetInformation(Playitem playitem) {
		
		/*
		if(playitem.Artist == null) {
			Log.d(TAG, "playitem.Artist is null.");
		}
		if(playitem.Album == null) {
			Log.d(TAG, "playitem.Album is null.");
		}
		if(playitem.Title == null) {
			Log.d(TAG, "playitem.Title is null.");
		}
		*/
		
		mInformation.setText(playitem.Artist + " - " + playitem.Album + " - " + playitem.Title);
		
	}
	
	public void SetTime(int totalTime, int currentTime, int status) {
		
		mTotalTime = totalTime;
		mCurrentTime = currentTime;
		
		mTime.setText(currentTime + "");
		
		mSeekBar.setMax(totalTime);
		mSeekBar.setProgress(currentTime);
		
		// Remove previous one.
		mHandler.removeCallbacks(mWalker);
		
		switch(status) {
		case PlayerService.STATUS_PLAYING:
			mHandler.postDelayed(mWalker, INTERVAL);
			break;
		case PlayerService.STATUS_PAUSING:
			break;
		}
		
	}
	
	public void SetStatus(int status) {
		
		switch(status) {
		case PlayerService.STATUS_PLAYING:
			mToggle.setImageResource(android.R.drawable.ic_media_pause);
			break;
		case PlayerService.STATUS_PAUSING:
			mToggle.setImageResource(android.R.drawable.ic_media_play);
			break;
		}
		
	}
	
	public void SetMode(int mode) {
		
		switch(mode) {
		case PlayerService.MODE_SINGLE:
			mMode.setImageResource(R.drawable.single);
			break;
		case PlayerService.MODE_REPEAT_TRACK:
			mMode.setImageResource(R.drawable.repeat_track);
			break;
		case PlayerService.MODE_REPEAT_PLAYLIST:
			mMode.setImageResource(R.drawable.repeat_playlist);
			break;
		case PlayerService.MODE_RANDOM:
			mMode.setImageResource(R.drawable.random);
			break;
		default:
			Log.d(TAG, mode + "");
			break;
		}
		
		mCurrentMode = mode;
		
	}
	
	public boolean Update() {
		
		PlayerService playerService = Utils.GetPlayerService(this);
		
		mCurrentPlayitem = playerService.GetCurrentPlayitem();
		int totalTime = playerService.GetTotalTime();
		int currentTime = playerService.GetCurrentTime();
		int status = playerService.GetStatus();
		int mode = playerService.GetMode();
		
		if(mCurrentPlayitem != null) {
			
			SetInformation(mCurrentPlayitem);
			SetTime(totalTime, currentTime, status);
			SetStatus(status);
			SetMode(mode);
			
			return true;
			
		}
		else {
			
			return false;
			
		}
		
	}

}
